package com.demo.woziqi;

import com.demo.woziqi.dao.ResultDao;
import com.demo.woziqi.dao.UserDAO;
import com.demo.woziqi.entity.AI;
import com.demo.woziqi.entity.Chess;
import com.demo.woziqi.entity.User;
import com.demo.woziqi.massageImp.*;
import com.demo.woziqi.message.*;
import com.demo.woziqi.util.GameConstant;
import com.demo.woziqi.util.GameModel;
import com.demo.woziqi.util.GameUtil;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

import java.util.Optional;

/**
 * @Author 宋明松
 * @Version V1.0.1
 * @Date 2022-06-02
 * <p>
 * 游戏面板，棋谱类
 */
public class GameFightStage extends Stage {
    public Pane panes = new Pane();
    public static boolean isPlay = true;// 是否可以落子
    public static boolean isBlack = true;

    public GameFightStage() {
        if (GameConstant.pattern == 2) {
            setTitle("五子棋");
            setHeight(GameConstant.HEIGHT);
            setWidth(GameConstant.WIDTH + 200);
            setResizable(false); // 固定大小
        } else {
            setTitle("五子棋");
            setHeight(GameConstant.HEIGHT);
            setWidth(GameConstant.WIDTH);
            setResizable(false); // 固定大小
        }

        GameLister butLister = new GameLister();
        butLister.getCheckerboard(panes, this); // 初始化棋盘及按钮监听事件处理

        this.setOnCloseRequest(e -> { // 关闭窗口事件监听
            if (GameConstant.chess.size() != 0) { // 棋盘上还有棋子,提示需要保存当前棋谱
                Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
                alert.setHeaderText("需要保存当前棋谱吗？");
                //显示对话框
                Optional<ButtonType> result = alert.showAndWait();
                if (result.get() == ButtonType.OK) { // 点击确定执行
                    GameUtil.chessNum = 0; // 棋子数清零
                    GameUtil.isWriteFile(this); // 保存棋谱
                }
                if (GameConstant.pattern == 2) { // 联机模式关闭窗口
                    if (result.get() == ButtonType.OK) { // 点击确定执行
                        GameUtil.chessNum = 0; // 棋子数清零
                        this.close(); // 关闭当前窗口
                        GameInputPortAndIPStage.inputStage.close(); // 关闭信息录入窗口
                    }
                }
                this.close(); // 关闭当前窗口
                GoApplicationStage.stage.show(); // 显示程序模式选择窗口
            } else { // 没有棋子直接关闭
                if (GameConstant.pattern == 2) { // 联机模式关闭窗口
                    this.close(); // 关闭当前窗口
                    GameInputPortAndIPStage.inputStage.close(); // 关闭信息录入窗口
                    GoApplicationStage.stage.show(); // 显示程序模式选择窗口
                } else { // 其他模式关闭
                    this.close(); // 关闭当前窗口
                    GoApplicationStage.stage.show(); //显示程序选择窗口
                }
            }
        });

        panes.setOnMouseClicked(e -> { // 为面板添加点击事件
            if (GameConstant.isEnd) { // 判断是否有棋子胜出，有就return。
                Alert alert = new Alert(Alert.AlertType.WARNING);// 提示信息
                alert.setHeaderText("请重新开始！");
                alert.show();
                return;
            }
            if (!isPlay) {
                return;
            }
            double x = e.getX(); // 获取点击后的坐标
            double y = e.getY();
            int _x = ((int) x - GameConstant.MARGIN + GameConstant.LINE_DISTANCE / 2) / GameConstant.LINE_DISTANCE; // 以第一个交叉点为原点（0,0）计算每个点的坐标，计算在棋谱中的坐标
            int _y = ((int) y - GameConstant.MARGIN + GameConstant.LINE_DISTANCE / 2) / GameConstant.LINE_DISTANCE;
            GameConstant._x = _x; // 赋值
            GameConstant._y = _y;

            // 判断点击的位置是否在棋盘内
            if (!(x >= GameConstant.MARGIN && x <= GameConstant.WIDTH - GameConstant.MARGIN && y >= GameConstant.MARGIN && y <= 100 + GameConstant.LINE_DISTANCE * (GameConstant.LINE_NUM - 1))) {
                return;
            }
            if (GameConstant.pattern == -1) { // 判断对局模式
                Alert alert = new Alert(Alert.AlertType.WARNING);// 提示信息
                alert.setHeaderText("请选择对局模式");
                alert.show();
            } else if (GameConstant.pattern == 0) {
                GameModel.isSingle(panes);
            } else if (GameConstant.pattern == 1) {
                // 人机模式，权重分析
                Circle circleBlack = new Circle(GameConstant._x * GameConstant.LINE_DISTANCE + GameConstant.MARGIN, GameConstant._y * GameConstant.LINE_DISTANCE + GameConstant.MARGIN, 20, Color.BLACK); // 传入时需要转换为坐标
                if (GameUtil.isExitAll(GameConstant._x, GameConstant._y)) {
                    return;
                }
                Chess blackChess = new Chess(GameConstant._x, GameConstant._y, 0);//创建黑棋
                GameConstant.chess.add(blackChess); // 添加黑棋
                panes.getChildren().add(circleBlack); // 将黑棋添加到棋盘中
                AI.setWeight(blackChess); // 赋予权值
                if (GameUtil.isWin(blackChess)==1) { // 判断胜负
                    GameConstant.isEnd = true; // 当前局结束，
                    Alert alert = new Alert(Alert.AlertType.INFORMATION); // 提示信息
                    alert.setHeaderText("恭喜，黑棋胜出！");
                    alert.show();
                }
                GameConstant.flag = false;
                GameModel.isMachine(panes);
            } else { // 联机模式
                UserDAO userDAO = new UserDAO(); // 实例化用户DAO类
                if (GameUtil.isExitAll(GameConstant._x, GameConstant._y)) { // 判断棋子是否重复
                    return;
                }
                Circle circleChess = new Circle(GameConstant._x * GameConstant.LINE_DISTANCE + GameConstant.MARGIN, GameConstant._y * GameConstant.LINE_DISTANCE + GameConstant.MARGIN, 20, isBlack ? Color.BLACK : Color.WHITE); // 传入时需要转换为坐标
                Chess chess = new Chess(GameConstant._x, GameConstant._y, isBlack ? 0 : 1);//创建棋
                //  结束后，还能落一子？（解决方法：应发消息告诉另一方游戏结束）
                if (GameUtil.isWin(chess)==1) { // 棋局分出胜负，客户端先弹出胜利者窗口
                    User u = new User();
                    u.setId(GameConstant.user.getId());  //实例化用户信息
                    if (chess.getColor() == 0) { // 黑棋胜
                        GameConstant.isEnd = true; // 当前局结束，
                        Alert alert = new Alert(Alert.AlertType.INFORMATION); // 提示信息
                        alert.setHeaderText("恭喜，黑棋胜出！");
                        alert.show();
                        isPlay = false; // 不能再落子
                        userDAO.userWinNum(u); //更新赢局数
                        userDAO.userAllNum(u); //TODO 总 更改对局数
                        // 将黑棋的用户ID发送到服务器，服务器端执行result表的更新操作
                        DBResultMessage dbResultMessage = new DBResultMessage();
                        dbResultMessage.setUserID(GameConstant.user.getId());
                        dbResultMessage.setRes("黑胜");
                        GameUtil.sendMessage(dbResultMessage);// 发送信息
                        User us = userDAO.getNumMsg(u); // 查询对局数，以及积分
                        GameConstant.user.setAll_count(us.getAll_count());
                        GameConstant.user.setWin_count(us.getWin_count());
                        GameConstant.user.setLose_count(us.getLose_count());
                        GameConstant.user.setDraw_count(us.getDraw_count());
                        GameConstant.user.setIntegral(us.getIntegral());
                        panes.getChildren().removeIf(c -> c instanceof Label); //移除pane中类型为Label的控件
                        GameLister.getLable(panes); // 重新加载右侧面板
                    } else {
                        GameConstant.isEnd = true; // 当前局结束，
                        Alert alert = new Alert(Alert.AlertType.INFORMATION);// 提示信息
                        alert.setHeaderText("恭喜，白棋胜出！");
                        alert.show();
                        isPlay = false;
                        userDAO.userWinNum(u); // 更新赢局数
                        userDAO.userAllNum(u); //TODO 总 更改对局数
                        //  将黑棋的用户ID发送到服务器，服务器端执行result表的更新操作
                        DBResultMessage dbResultMessage = new DBResultMessage();
                        dbResultMessage.setUserID(GameConstant.user.getId());
                        dbResultMessage.setRes("白胜");
                        GameUtil.sendMessage(dbResultMessage); // 发送信息
                        User us = userDAO.getNumMsg(u); // 查询对局数，以及积分
                        GameConstant.user.setAll_count(us.getAll_count()); // 更新查询到的数据
                        GameConstant.user.setWin_count(us.getWin_count());
                        GameConstant.user.setLose_count(us.getLose_count());
                        GameConstant.user.setDraw_count(us.getDraw_count());
                        GameConstant.user.setIntegral(us.getIntegral());
                        panes.getChildren().removeIf(c -> c instanceof Label); //移除pane中类型为Label的控件
                        GameLister.getLable(panes); // 重新加载右侧面板
                    }

                    GameOverMessage gameOverMessage = new GameOverMessage(); // 实例化游戏结束消息
                    gameOverMessage.setChess(chess);// 添加胜方棋子
                    GameUtil.sendMessage(gameOverMessage); // 发送最后一枚棋子（胜者棋子）,给对方提示胜利信息
                }else if(GameUtil.isWin(chess)==2) { //todo 和棋(没有分出胜负，但不代表和棋）
                    StalemateMessage stalemateMessage= new StalemateMessage();
                    if(!GameUtil.sendMessage(stalemateMessage)){//发送和棋消息,排除对方未上线BUG
                        return;
                    }
                    User u = new User();
                    u.setId(GameConstant.user.getId());  //实例化用户信息
                    userDAO.userStalemateNum(u);
                    panes.getChildren().removeIf(c -> c instanceof Label); //移除pane中类型为Label的控件
                    GameLister.getLable(panes); // 重新加载右侧面板
                }
                ChessMessage chessMessage = new ChessMessage();
                chessMessage.setX(GameConstant._x);
                chessMessage.setY(GameConstant._y);
                chessMessage.setColor(isBlack);
                if (GameUtil.sendMessage(chessMessage)) { // 发送棋子信息消息,发送成功
                    panes.getChildren().add(circleChess); // 将棋添加到棋盘中
                    GameConstant.chess.add(chess); // 添加棋到集合
                    isPlay = false;
                    isBlack = !isBlack;
                }
            }
        });
        Scene scene = new Scene(panes); // 场景，存放面板
        scene.getStylesheets().add(String.valueOf(getClass().getClassLoader().getResource("scratch.css"))); //引入css
        this.setScene(scene); // 将场景设置到主舞台
        this.show();
    }

    /**
     * 服务器线程的信息处理方法
     *
     * @param messages
     */
    public void processMessage(Message messages) { // 棋子信息处理
        if (messages instanceof ChessMessage) {
            ChessMessage chessMessage = (ChessMessage) messages;
            //更新UI
            Circle circleChess = new Circle(chessMessage.getX() * GameConstant.LINE_DISTANCE + GameConstant.MARGIN, chessMessage.getY() * GameConstant.LINE_DISTANCE + GameConstant.MARGIN, 20, chessMessage.getColor() ? Color.BLACK : Color.WHITE); // 传入时需要转换为坐标
            panes.getChildren().add(circleChess); // 将黑棋添加到棋盘中
            Chess chess = new Chess(chessMessage.getX(), chessMessage.getY(), chessMessage.getColor() ? 0 : 1);
            GameConstant.chess.add(chess); // 添加棋到集合
            isPlay = true;
            isBlack = !isBlack;
        } else if (messages instanceof NewGameMessage) { // 对局没结束 新开一局确认处理
            if (!GameUtil.isAgree()) {// 调用 新开窗口，确认是否新局 返回true表示同意
                System.out.println("我不同意重开！！！");// TODO
                return; // 终止程序
            }
            IsNewGameMassage isNewGameMassage = new IsNewGameMassage(); // 实例化同意重开信息对象
            isNewGameMassage.setNewGame(true);  // 设置属性为true，表示同意重开
            GameUtil.sendMessage(isNewGameMassage); // 发送同意重开消息给客户端处理
            // 清除接收程序的面板（服务器端的面板）
            GameLister gameLister = new GameLister();
            GameConstant.chess.clear(); // 清除list中的棋子
            panes.getChildren().clear(); // 清除面板中所有元素
            isPlay = true; // 可以落子状态
            isBlack = true; // 重置棋子为黑棋
            GameConstant.isEnd = false; // 对局未结束状态
            UserDAO userDAO = new UserDAO();
            User user = new User();
            user.setId(GameConstant.user.getId());
            if (GameConstant.isEnd){
                userDAO.userAllNum(user); // 更改对局数
            }
            User u = userDAO.getNumMsg(user); // 查询对局数，以及积分
            GameConstant.user.setAll_count(u.getAll_count());
            gameLister.getCheckerboard(panes, this);// 重写绘制节点，并加载鼠标点击事件
        } else if (messages instanceof IsNewGameMassage) { // 处理同意重开的消息逻辑
            System.out.println("对方同意重开");// TODO
            // 清除发送程序的面板（客户端的面板）
            GameLister gameLister = new GameLister();
            GameConstant.chess.clear(); // 清除list中的棋子
            GameConstant.isEnd = false; // 对局未结束状态
            panes.getChildren().clear(); // 清除面板中所有元素
            isPlay = true; // 可以落子
            isBlack = true; // 重置棋子为黑棋
            UserDAO userDAO = new UserDAO();
            User user = new User();
            user.setId(GameConstant.user.getId());
            if (GameConstant.isEnd){
                userDAO.userAllNum(user); // 更改对局数
            }
            User u = userDAO.getNumMsg(user); // 查询对局数，以及积分
            GameConstant.user.setAll_count(u.getAll_count());
            gameLister.getCheckerboard(panes, this);// 重写绘制节点，并加载鼠标点击事件
        } else if (messages instanceof GameOverNewMassage) { // 对局结束新开一局消息处理
            // 清除发送程序的面板
            GameLister gameLister = new GameLister();
            GameConstant.chess.clear(); // 清除list中的棋子
            GameConstant.isEnd = false; // 移除结束判断
            panes.getChildren().clear(); // 清除面板中所有元素
            isPlay = true;
            isBlack = true;
            UserDAO userDAO = new UserDAO();
            User user = new User();
            user.setId(GameConstant.user.getId());
            if (GameConstant.isEnd){
                userDAO.userAllNum(user); // 更改对局数
            }
            User u = userDAO.getNumMsg(user); // 查询对局数，以及积分
            GameConstant.user.setAll_count(u.getAll_count());
            gameLister.getCheckerboard(panes, this);// 重写绘制节点，并加载鼠标点击事件
        } else if (messages instanceof GameOverMessage) { // 分出胜负，游戏结束消息处理
            System.out.println("游戏结束！"); // todo
            User u = new User();
            u.setId(GameConstant.user.getId());  //实例化用户信息
            UserDAO userDAO = new UserDAO();
            GameOverMessage gameOverMessage = (GameOverMessage) messages;
            if (gameOverMessage.getChess().getColor() == 0) { // 黑棋胜
                GameConstant.isEnd = true; // 当前局结束，
                Alert alert = new Alert(Alert.AlertType.INFORMATION); // 提示信息
                alert.setHeaderText("恭喜，黑棋胜出！");
                alert.show();
                isPlay = false;
                userDAO.userLostNum(u); // 更新输局数
                userDAO.userAllNum(u); //TODO 总 更改对局数
                User us = userDAO.getNumMsg(u); // 查询对局数，以及积分
                GameConstant.user.setAll_count(us.getAll_count()); // 将查询的数据更新
                GameConstant.user.setWin_count(us.getWin_count());
                GameConstant.user.setLose_count(us.getLose_count());
                GameConstant.user.setDraw_count(us.getDraw_count());
                GameConstant.user.setIntegral(us.getIntegral());
                panes.getChildren().removeIf(c -> c instanceof Label); //移除pane中类型为Label的控件
                GameLister.getLable(panes); // 重新加载右侧面板
            } else {
                GameConstant.isEnd = true; // 当前局结束，
                Alert alert = new Alert(Alert.AlertType.INFORMATION);// 提示信息
                alert.setHeaderText("恭喜，白棋胜出！");
                alert.show();
                isPlay = false;
                userDAO.userLostNum(u); // 更新输局数
                userDAO.userAllNum(u); //TODO 总 更改对局数
                User us = userDAO.getNumMsg(u); // 查询对局数，以及积分
                GameConstant.user.setAll_count(us.getAll_count());
                GameConstant.user.setWin_count(us.getWin_count());
                GameConstant.user.setLose_count(us.getLose_count());
                GameConstant.user.setDraw_count(us.getDraw_count());
                GameConstant.user.setIntegral(us.getIntegral());
                panes.getChildren().removeIf(c -> c instanceof Label); //移除pane中类型为Label的控件
                GameLister.getLable(panes); // 重新加载右侧面板
            }
        } else if (messages instanceof RegretChessMessage) { // 悔棋消息处理
            if (!GameUtil.isAgreeRegret()) {// 新开窗口，确认是否同意悔棋？
                System.out.println("我不同意悔棋！！！"); // TODO
                return; // 终止程序
            }
            IsRegretChessMessage isRegretChessMessage = new IsRegretChessMessage();
            isRegretChessMessage.setRegretChessMessage(true); // 同意悔棋
            GameUtil.sendMessage(isRegretChessMessage); // 发送同意悔棋消息给客户端处理
            if (GameConstant.chess.size() == 0) { // 面板上棋子悔完，不执行
                return;
            }
            panes.getChildren().remove(panes.getChildren().size() - 1);//todo 移除面板上的最后一枚棋子
            GameLister.getLable(panes); // 重新加载右侧面板
            GameConstant.chess.remove(GameConstant.chess.size() - 1); // 移除最后一枚棋子
            isPlay = false; // 悔棋后对方不能再落子
            GameFightStage.isBlack = !GameFightStage.isBlack; // 颜色取反
        } else if (messages instanceof IsRegretChessMessage) { // 同意悔棋消息处理
            System.out.println("对方同意悔棋");// TODO
            GameUtil.regretChess(panes); // 客户端悔棋删除棋子
            GameLister.getLable(panes); // 重新加载右侧面板
            GameFightStage.isPlay = true;  // 客户端棋盘可以落子
            GameConstant.isEnd=false; // 客户端棋盘可以落子
            GameFightStage.isBlack = !GameFightStage.isBlack;  //颜色取反
        } else if (messages instanceof DBResultMessage) {
            DBResultMessage dbResultMessage = (DBResultMessage) messages;
            ResultDao resultDao = new ResultDao();
            resultDao.setResult(dbResultMessage.getUserID(), GameConstant.user.getId(), dbResultMessage.getRes());
            panes.getChildren().removeIf(c -> c instanceof Label); //移除pane中类型为Label的控件
            GameLister.getLable(panes); // 重新加载右侧面板
        }else if (messages instanceof StalemateMessage){ // 服务器端和棋消息处理方法
            User u = new User();
            u.setId(GameConstant.user.getId());  //实例化用户信息
            UserDAO userDAO = new UserDAO();
            userDAO.userStalemateNum(u); // 用户和棋数量加1
            panes.getChildren().removeIf(c -> c instanceof Label); //移除pane中类型为Label的控件
            GameLister.getLable(panes); // 重新加载右侧面板
        }
    }
}
